package com.codepuzzler;

import org.apache.log4j.Logger;

import java.util.*;

public class TreeMaxLengthCalculator {

    private static final Logger LOGGER = Logger.getLogger(TreeMaxLengthCalculator.class);

    public static void main(String[] args) throws Exception {
        new TreeMaxLengthCalculator().calculate();
    }

    void calculate() {
        Queue<TreeNode> tree = initTree();
        while (tree.size() > 1) {
            LOGGER.info("Queue size " + tree.size());
            TreeNode node = tree.poll();

            LOGGER.info("Process Node " + node.getLabel());

            if (!node.isLeaf()) {
                LOGGER.info("Re-add Node " + node.getLabel() + " into the tree");
                tree.add(node);
            }

            if (node.isMinimumTree()) {
                LOGGER.info("Node " + node.getLabel() + " is a minimum tree");

                int max = node.getValue();
                for (TreeNode child : node.getChildren()) {
                    max = max > node.getValue() + child.getValue() ? max : node.getValue() + child.getValue();
                    tree.remove(child);
                }

                node.setValue(max);
                LOGGER.info("Node " + node.getLabel() + "'s value is reset as " + node.getValue());

                node.setChildren(new HashSet<TreeNode>());
            }
        }

        System.out.println(tree.poll().getValue());
    }

    private Queue<TreeNode> initTree() {
        Queue<TreeNode> tree = new LinkedList<TreeNode>();

        TreeNode nodeA = new TreeNode("A", 5);
        TreeNode nodeB = new TreeNode("B", 7);
        TreeNode nodeC = new TreeNode("C", 2);
        TreeNode nodeD = new TreeNode("D", 8);
        TreeNode nodeE = new TreeNode("E", 4);
        TreeNode nodeF = new TreeNode("F", 3);
        TreeNode nodeG = new TreeNode("G", 5);

        nodeA.addChild(nodeB);
        nodeA.addChild(nodeC);

        nodeB.setParent(nodeA);
        nodeB.addChild(nodeD);
        nodeB.addChild(nodeE);

        nodeC.setParent(nodeA);
        nodeC.addChild(nodeF);
        nodeC.addChild(nodeG);

        nodeD.setParent(nodeB);
        nodeE.setParent(nodeB);

        nodeF.setParent(nodeC);
        nodeG.setParent(nodeC);

        tree.add(nodeA);
        tree.add(nodeB);
        tree.add(nodeC);
        tree.add(nodeD);
        tree.add(nodeE);
        tree.add(nodeF);
        tree.add(nodeG);

        return tree;
    }
}
